package com.gis.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gis.dto.SedimentReportDTO;
import com.gis.entity.EcologyData;
import com.gis.entity.StationData;
import com.gis.entity.WaterQualityData;
import com.gis.exception.CustomException;
import com.gis.maps.commonMap;
import com.gis.service.StationDataService;
import com.gis.utils.PythonUtil;
import jakarta.servlet.ServletOutputStream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gis.entity.SedimentData;
import com.gis.mapper.SedimentDataMapper;
import com.gis.service.SedimentDataService;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import static org.apache.commons.lang.StringUtils.capitalize;

@Slf4j
@Service
public class SedimentDataServiceImpl extends ServiceImpl<SedimentDataMapper, SedimentData> implements SedimentDataService {

    @Autowired
    private SedimentDataMapper sedimentDataMapper;
    @Autowired
    private StationDataService stationDataService;
    @Value("${python.path}")
    private String pythonPath;
    @Autowired
    private PythonUtil pythonUtil;

    @Override
    public List<SedimentReportDTO> getSedimentQualityAvgByYearAndSeason(int year, String season) {
        return sedimentDataMapper.getSedimentQualityAvgByYearAndSeason(year, season);
    }

    @Override
    public List<Float> getLastN(String param, int n, int id) {
        List<Float> data = new ArrayList<>();
        List<SedimentData> sedimentData = sedimentDataMapper.getLastN(param, n, id);
        for(SedimentData s : sedimentData){
            String methodName = "get" + capitalize(commonMap.getParam(param));
            try {
                Method method = WaterQualityData.class.getMethod(methodName);
                Float result = (Float) method.invoke(s);
                data.add(result);
            } catch (NoSuchMethodException e) {
                throw new CustomException("反射错误");
            } catch (InvocationTargetException e) {
                throw new CustomException("反射错误");
            } catch (IllegalAccessException e) {
                throw new CustomException("反射错误");
            }
        }
        return data;
    }

    @Override
    public void generateTIF(ServletOutputStream outputStream, String param, int year, String season) {
        List<SedimentData> sedimentDataList = getAllByYearAndSeason(year, season);
        List<List<Float>> tripleList = new ArrayList<>();
        for(SedimentData sedimentData : sedimentDataList){
            String methodName = "get" + capitalize(param);
            Method method = null;
            try {
                method = SedimentData.class.getMethod(methodName);
                Float paramValue = (Float) method.invoke(sedimentData);
                if(paramValue != null){
                    StationData stationData = stationDataService.getById(sedimentData.getStationId());
                    List<Float> data= new ArrayList<>();
                    data.add(stationData.getLongitude());
                    data.add(stationData.getLatitude());
                    data.add(paramValue);
                    tripleList.add(data);
                }
            } catch (NoSuchMethodException e) {
                throw new CustomException("反射错误");
            } catch (InvocationTargetException e) {
                throw new CustomException("反射错误");
            } catch (IllegalAccessException e) {
                throw new CustomException("反射错误");
            }
        }
        if(tripleList.isEmpty()){
            log.info("无数据进行空间分析");
            throw new CustomException("无数据进行空间分析");
        }
        boolean success = pythonUtil.runSpatialAnalysis(tripleList);
        if(success){
            String tifPath = pythonPath + "/tif/output.tif";
            File file = new File(tifPath);
            try (FileInputStream fis = new FileInputStream(file);
                 BufferedInputStream bis = new BufferedInputStream(fis)) {
                byte[] bytes = new byte[(int) file.length()];
                int bytesRead = bis.read(bytes);
                if (bytesRead != -1) {
                    outputStream.write(bytes, 0, bytesRead);
                }
            } catch (IOException e) {
                throw new CustomException("文件读取或写入失败");
            }
        }else {
            throw new CustomException("空间分析失败");
        }
    }

    @Override
    public List<SedimentData> getAllByYearAndSeason(int year, String season) {
        QueryWrapper<SedimentData> wrapper = new QueryWrapper<SedimentData>()
                .eq("year", year)
                .eq("season", season);
        return sedimentDataMapper.selectList(wrapper);
    }

    /**
     * 获取指定站点时间范围内的数据
     * @param stationId
     * @param fromYear
     * @param fromSeason
     * @param toYear
     * @param toSeason
     * @return
     */
    @Override
    public List<SedimentData> getFromYearAndSeason(int stationId, int fromYear, String fromSeason, int toYear, String toSeason) {
        List<SedimentData> sedimentDataList = sedimentDataMapper.getFromYear(stationId, fromYear, toYear);
        List<SedimentData> result = new ArrayList<>();
        for (SedimentData sedimentData : sedimentDataList){
            if(sedimentData.getYear()==fromYear){
                if(fromSeason.equals("fall")&&sedimentData.getSeason().equals("spring")){
                    continue;
                }
            }
            if(sedimentData.getYear()==toYear){
                if(toSeason.equals("spring")&&sedimentData.getSeason().equals("fall")){
                    continue;
                }
            }
            result.add(sedimentData);
        }
        return result;
    }
}
